package cn.com.cc.parse;
/**
 * 此类主要作用是把Map转换成xml格式
 */
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import cn.com.cc.constant.Constants;
import cn.com.cc.log.Logger;

public class XMLEncoder {
	
	private String encoding = "UTF-8";
	
	@SuppressWarnings("unchecked")
	public String encoderMap(Map xmlMap){
		Document doc = encoderMapDoc(xmlMap);
		Logger.debug(doc.asXML());
		return doc.asXML();
	}
	
	/**
	 * 如果xmlMap所对应的key-->HEAD,CONTENT,TAIL 有值的化插入Map
	 * @param xmlMap
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Document encoderMapDoc(Map xmlMap){
		if(xmlMap == null || xmlMap.size() == 0){
			Logger.debug(new StringBuffer().append("###cn.com.parse.XMLEncoder.encoderMapDoc(Map xmlMap)--->xmlMap is null || xmlMap.size() == 0").toString());
			return null;
		}
		InputStream in = new ByteArrayInputStream("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Message><HEAD></HEAD><CONTENT></CONTENT><TAIL></TAIL></Message>".getBytes());
		Document doc = getDoc(in);
		Set xmlSet = xmlMap.keySet();
		Element rootElement = doc.getRootElement();
		String position = null;
		Map map = null;
		Element mapElement = null;
		for(Iterator it = xmlSet.iterator();it.hasNext();addMapElement(map, mapElement)){
			position = (String)it.next();
			map = (Map)xmlMap.get(position);
			Element element = rootElement.element(position);
			mapElement = element.addElement("Map");
		}
		return doc;
	}
	
	/**
	 * SAX解析xml,返回doc
	 * @param in
	 * @return
	 */
	@SuppressWarnings("unused")
	private Document getDoc(InputStream in){
		SAXReader reader = new SAXReader();
		reader.setEncoding(encoding);
		Document doc = null;
		try {
			doc = reader.read(in);
		} catch (DocumentException e) {
			Logger.info(new StringBuffer().append("###cn.com.parse.XMLEncoder.getDoc(InputStream in)--->get document throws exception").toString());
			e.printStackTrace();
		}
		return doc;
	}
	
	/**
	 * 在Map中加入Item,Item中加入Key
	 * @param map
	 * @param mapElement
	 */
	@SuppressWarnings("unchecked")
	private void addMapElement(Map map, Element mapElement){
		Set mapSet = map.keySet();
		Element itemElement = null;
		Element keyElement = null;
		String key = null;
		Object value = null;
		for(Iterator it = mapSet.iterator();it.hasNext();addValueElement(itemElement, value)){
			key = (String)it.next();
			value = map.get(key);
			if(value == null){
				value = "NULL";
			}
			itemElement = mapElement.addElement("Item");
			keyElement = itemElement.addElement("Key");
			keyElement.setText(key);
		}
	}
	
	/**
	 * 在Item中加入Value和Key匹配,并且判断Value中的值类型,不同类型加入的方法不一样
	 * @param itemElement
	 * @param value
	 */
	private void addValueElement(Element itemElement, Object value){
		if(value instanceof String) {
			String str = getValue((String) value);
			Element valueElement = itemElement.addElement("Value");
			valueElement.setText(str);
		}else if(value instanceof Map){
			Element valueElement = itemElement.addElement("Value");
			Map map = (Map)value;
			Set set = map.keySet();
			Element keyElement = null;
			Element item = null;
			String key = null;
			Object valueObj = null;
			for(Iterator it = set.iterator();it.hasNext();addValueElement(item,valueObj)){
				key = (String)it.next();
				valueObj = map.get(key);
				item = valueElement.addElement("Item");
				keyElement = item.addElement("Key");
				keyElement.setText(key);
			}
		}else if(value instanceof Array[]){
			String[] array = (String[])value;
			String s = "";
			boolean flag = false;
			for(int i=0; i<array.length; i++){
				s += array[i] + ",";
				flag = true;
			}
			if(flag){
				s.substring(0, s.length() - 1);
			}
			Element valueElement = itemElement.addElement("Value");
			valueElement.setText(s.trim());
		}else if(value instanceof List){
			List list = (List)value;
			if(list.size() != 0 && list != null){
				Object obj = list.get(0);
				if(obj instanceof String){
					
				}else if(obj instanceof Character){
					
				}else if(obj instanceof Byte){
					
				}else if(obj instanceof Integer){
					
				}else if(obj instanceof Double){
					
				}else if(obj instanceof Float){
					
				}else{
					Element valueElement = itemElement.addElement("Value");
					valueElement.setText("NULL");
					Logger.warn(new StringBuffer().append("###cn.com.parse.XMLEncoder.addValueElement(Element itemElement, Object value)--->Because of your value type(List<E>) is incorrect, cause analysis problems").toString());
				}
			}else{
				Element valueElement = itemElement.addElement("Value");
				valueElement.setText("NULL");
			}
		}else{
			Element valueElement = itemElement.addElement("Value");
			valueElement.setText("NULL");
			Logger.warn(new StringBuffer().append("###cn.com.parse.XMLEncoder.addValueElement(Element itemElement, Object value)--->Because of your value type is incorrect, cause analysis problems").toString());
		}
	}
	
	
	private String getValue(String str){
		if(str == null){
			str = "NULL";
		}
		return str.trim();
	}
	
	public static void main(String[] args){
		Map headMap = new LinkedHashMap();
		Map dataMap = new LinkedHashMap();
		Map tailMap = new LinkedHashMap();
		Map xmlMap = new LinkedHashMap();
		Map a = new LinkedHashMap();
		a.put("ggg", "777");
		a.put("hhh", "888");
		a.put("iii", "999");
		headMap.put("aaa", "");
		headMap.put("bbb", "222");
		dataMap.put("ccc", "333");
		dataMap.put("ddd", "444");
		dataMap.put("jjj", a);
		tailMap.put("eee", "嘿嘿");
		tailMap.put("fff", "666");
		xmlMap.put(Constants.HEAD, headMap);
		xmlMap.put(Constants.CONTNET, dataMap);
		xmlMap.put(Constants.TAIL, tailMap);
		XMLEncoder encoder = new XMLEncoder();
		System.out.println(encoder.encoderMap(xmlMap));
	}

}
